(function (factory) {
  typeof define === 'function' && define.amd ? define(factory) :
  factory();
})((function () { 'use strict';

  // 页面性能监控
  var processData$2 = function processData(p) {
    var data = {
      prevPage: p.fetchStart - p.navigationStart,
      // 上一个页面到这个页面的时长
      redirect: p.redirectEnd - p.redirectStart,
      // 重定向时长
      dns: p.domainLookupEnd - p.domainLookupStart,
      // DNS解析时长
      connect: p.connectEnd - p.connectStart,
      // TCP连接时长

      send: p.responseEnd - p.requestStart,
      // 请求总时长 响应结束到请求开始
      ttfb: p.responseStart - p.navigationStart,
      // 首字节时间
      domready: p.domInteractive - p.domLoading,
      // DOM准备时长
      whiteScreen: p.domLoading - p.navigationStart,
      // 白屏时长
      dom: p.domComplete - p.domLoading,
      // DOM解析时长
      load: p.loadEventEnd - p.loadEventStart,
      // 页面加载时长
      total: p.loadEventEnd - p.navigationStart // 总时长
    };
    return data;
  };
  var load = function load(cb) {
    var timer;
    var check = function check() {
      if (performance.timing.loadEventEnd) {
        clearTimeout(timer);
        cb();
      } else {
        timer = setTimeout(check, 100);
      }
    };
    window.addEventListener("load", check, false);
  };
  var domready = function domready(cb) {
    var timer;
    var check = function check() {
      if (performance.timing.domInteractive) {
        clearTimeout(timer);
        cb();
      } else {
        timer = setTimeout(check, 100);
      }
    };
    window.addEventListener("DOMContentLoaded", check, false);
  };
  var perf = {
    init: function init(cb) {
      domready(function () {
        //有可能没触发onload事件 dom解析完成后也需要先统计下，可能用户没加载完就关闭了页面
        var p = performance.timing;
        var data = processData$2(p);
        data.type = "domready";
        cb(data);
      });
      load(function () {
        var p = performance.timing;
        var data = processData$2(p);
        data.type = "loaded";
        cb(data);
      });
    }
  };

  var processData$1 = function processData(item) {
    var data = {
      name: item.name,
      initiatorType: item.initiatorType,
      duration: item.duration
    };
    return data;
  };
  var resource = {
    init: function init(cb) {
      //获取资源相关信息
      if (window.PerformanceObserver) {
        var observer = new PerformanceObserver(function (list) {
          var data = list.getEntries();
          cb(processData$1(data[0]));
        });
        observer.observe({
          entryTypes: ["resource"]
        });
      } else {
        window.onload = function () {
          var data = performance.getEntriesByType("resource").map(function (item) {
            return processData$1(item);
          });
          cb(data);
        };
      }
    }
  };

  var xhr = {
    init: function init(cb) {
      // 发送请求有两种 fetch xhr
      var xhr = window.XMLHttpRequest;
      var oldOpen = xhr.prototype.open;
      xhr.prototype.open = function (method, url, async, username, password) {
        this.info = {
          method: method,
          url: url,
          async: async,
          username: username,
          password: password
        };
        return oldOpen.apply(this, arguments);
      };
      var oldSend = xhr.prototype.send;
      xhr.prototype.send = function (value) {
        var _this = this;
        if (this.info) {
          this.info.startTime = Date.now();
          var fn = function fn(type) {
            return function () {
              _this.info.endTime = Date.now();
              _this.info.time = Date.now() - _this.info.startTime;
              _this.info.requesestSize = value ? value.length : 0;
              _this.info.responseSize = _this.responseText.length;
              _this.info.type = type;
              cb(_this.info);
            };
          };
          this.addEventListener("load", fn("load"), false);
          this.addEventListener("error", fn("error"), false);
          this.addEventListener("abort", fn("abort"), false);
        }
        return oldSend.apply(this, arguments);
      };
      //window.fetch
    }
  };

  function _iterableToArrayLimit(r, l) {
    var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
    if (null != t) {
      var e,
        n,
        i,
        u,
        a = [],
        f = !0,
        o = !1;
      try {
        if (i = (t = t.call(r)).next, 0 === l) {
          if (Object(t) !== t) return;
          f = !1;
        } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
      } catch (r) {
        o = !0, n = r;
      } finally {
        try {
          if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
        } finally {
          if (o) throw n;
        }
      }
      return a;
    }
  }
  function _slicedToArray(arr, i) {
    return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
  }
  function _arrayWithHoles(arr) {
    if (Array.isArray(arr)) return arr;
  }
  function _unsupportedIterableToArray(o, minLen) {
    if (!o) return;
    if (typeof o === "string") return _arrayLikeToArray(o, minLen);
    var n = Object.prototype.toString.call(o).slice(8, -1);
    if (n === "Object" && o.constructor) n = o.constructor.name;
    if (n === "Map" || n === "Set") return Array.from(o);
    if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
  }
  function _arrayLikeToArray(arr, len) {
    if (len == null || len > arr.length) len = arr.length;
    for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
    return arr2;
  }
  function _nonIterableRest() {
    throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
  }

  var processData = function processData(error) {
    var data = {
      message: error.message,
      name: error.name
    };
    var stack = error.stack;
    var matchUrl = stack.match(/http:\/\/[^\n]*/)[0];
    console.log(matchUrl);
    data.fileName = matchUrl.match(/http:\/\/(?:\S*)\.js/)[0];
    var _matchUrl$match = matchUrl.match(/:(\d+):(\d+)/),
      _matchUrl$match2 = _slicedToArray(_matchUrl$match, 3),
      row = _matchUrl$match2[1],
      column = _matchUrl$match2[2];
    data.row = row;
    data.column = column; //上线代码会压缩 source-map 映射 找到真实的报错
    return data;
  };
  var errorCatch = {
    init: function init(cb) {
      //无法监听图片错误
      // window.addEventListener('error',fn,true);  //捕获阶段
      // promise 错误无法捕获 windiw.addEventListener('unhandledrejection',fn);
      window.onerror = function (message, source, lineno, colno, error) {
        console.dir(error);
        var data = processData(error);
        cb(data);
      };
    }
  };

  // 监控页面性能 算时间差  Performance API
  var formatData = function formatData(data) {
    var arr = [];
    for (var key in data) {
      arr.push("".concat(key, "=").concat(data[key]));
    }
    return arr.join("&");
  };
  perf.init(function (data) {
    //获取到页面性能相关的数据
    //上报到后台 1.图片携带参数 new Image().src = "http://www.baidu.com/a.gif?name=xxx&age=18" 2.使用ajax 3.使用websocket

    new Image().src = "http://www.baidu.com/a.gif?" + formatData(data);
    console.log(data);
  });
  resource.init(function (data) {
    //上报到后台
    console.log(data);
  });
  xhr.init(function (data) {
    //上报到后台
    console.log(data);
  });
  errorCatch.init(function (data) {
    //上报到后台
    console.log(data);
  });
  //监控用户的行为

}));
